package com.ys.service.finance.impl;

import com.ys.entity.finance.TcwFinanceSalaryClassify;
import com.ys.entity.finance.TcwFinanceSalaryTotal;
import com.ys.mapper.finance.FinanceMapper;
import com.ys.mapper.finance.TcwFinanceSalaryTotalMapper;
import com.ys.service.finance.TcwFinanceSalaryTotalService;
import com.ys.util.CheckUtil;
import com.ys.vo.R;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 财务工资小计汇总表
 */
@Service("tcwFinanceSalaryTotalService")
public class TcwFinanceSalaryTotalServiceImpl implements TcwFinanceSalaryTotalService {
	private static final Logger logger = LoggerFactory.getLogger(TcwFinanceSalaryTotalServiceImpl.class);

	@Autowired
	private TcwFinanceSalaryTotalMapper tcwFinanceSalaryTotalMapper;

	@Autowired
	private FinanceMapper financeMapper;

	@Autowired
	private CheckUtil checkUtil;

	/**
	 * 根据所选择的月份，更新汇总数据
	 */
	@Override
	public R updateTotalByCountMonth(String countMonth) throws Exception{
		logger.info("更新月份:"+countMonth);

		List<TcwFinanceSalaryTotal> addlist = new ArrayList<>();

		//获取小计部门维护表信息
		List<Map<String,Object>> salaryList = new TcwFinanceSalaryClassify()
				.addLeftJoin("TS_OrganizationInfo O ON O.Orgid = A.Orgid ")
				.addField("CASE WHEN O.Orgid = 'D250' THEN '研发部' WHEN O.Orgid = 'C101' THEN '总裁办' ELSE O.OrgName END orgName")//部门名称
				.addField("O.OrgPathAll AS orgPathAll")//部门路径
				.setOrderby("A.ClassifyName ASC,A.Orgid ASC")
				.queryMap();

		if(salaryList==null || salaryList.size()<=0){
			return R.error("请先维护部门小计的关联信息");
		}
		//获取部门统计信息
		List<Map<String, Object>> countByDeptList = financeMapper.countFinanceSalaryTotalByDept(countMonth);
		//获取部门小计统计信息
		List<Map<String, Object>> countByClassifyNameList = financeMapper.countFinanceSalaryTotalByClassifyName(countMonth);

		logger.info("部门统计信息:"+countByDeptList);
		logger.info("部门小计统计信息:"+countByClassifyNameList);

		//是否属于销售部判断
		//属于销售部的进行汇总
		Predicate<Map<String, Object>> isBelongSale = countItem->
				countItem.get("orgPathAll").toString().contains("C101.D242") && //根据部门路径获取属于销售部的部门
				!"C101.D242.D243".equals(countItem.get("orgPathAll").toString()) && //排除市场部
						!"D242".equals(countItem.get("deptId").toString());//排除运营事业部

		//String classifyName = salaryList.get(0).get("classifyName").toString();
		if(countByDeptList!=null){
			for(int i=0;i<salaryList.size();i++){
				Map<String,Object> salaryItem = salaryList.get(i);

				//部门小计统计信息的判断与新增
				String classifyNameByThis = salaryItem.get("classifyName").toString();
				if(i!=0){
					if(!salaryList.get(i-1).get("classifyName").toString().equals(classifyNameByThis) && countByClassifyNameList!=null){//如果切换小计关系了，则添加小计信息
						final String classifyNameBySearch = salaryList.get(i-1).get("classifyName").toString();
						List<Map<String, Object>> countByClassifyName = countByClassifyNameList.stream()
								.filter(item->item.get("classifyName").toString().equals(classifyNameBySearch))
								.collect(Collectors.toList());
						if(countByClassifyName.size()>0){
							for(Map<String, Object> countItem : countByClassifyName){
								TcwFinanceSalaryTotal entityByTotal =  addCountDate(countItem);
								entityByTotal.setCountMonth(countMonth);//统计年月
								entityByTotal.setDeptName(countItem.get("classifyName").toString());//
								entityByTotal.setCountType(1);
								entityByTotal.setDeptType(0);
								addlist.add(entityByTotal);
							}
						}
					}
				}

				//部门统计数据
				List<Map<String, Object>> countByDept = countByDeptList.stream()
						.filter(item->item.get("deptId").toString().equals(salaryItem.get("orgid").toString()))
						.collect(Collectors.toList());
				if(countByDept.size()>0){
					for(Map<String, Object> countItem : countByDept){
						TcwFinanceSalaryTotal entity = addCountDate(countItem);
						entity.setCountMonth(countMonth);//统计年月
						entity.setDeptName(salaryItem.get("orgName").toString());
						entity.setCountType(0);
						if(isBelongSale.test(countItem)){//属于销售部
							entity.setDeptType(1);
						}else {//其他
							entity.setDeptType(0);
						}
						addlist.add(entity);
					}

				}

				//最后一条小计信息
				if(i==salaryList.size()-1){
					final String classifyNameBySearch = salaryList.get(i).get("classifyName").toString();
					List<Map<String, Object>> countByClassifyName = countByClassifyNameList.stream()
							.filter(item->item.get("classifyName").toString().equals(classifyNameBySearch))
							.collect(Collectors.toList());
					if(countByClassifyName.size()>0){
						for(Map<String, Object> countItem : countByClassifyName){
							TcwFinanceSalaryTotal entityByTotal =  addCountDate(countItem);
							entityByTotal.setCountMonth(countMonth);//统计年月
							entityByTotal.setDeptName(countItem.get("classifyName").toString());//
							entityByTotal.setCountType(1);
							entityByTotal.setDeptType(0);
							addlist.add(entityByTotal);
						}
					}
				}
			}
		}


		//新数据
		List<TcwFinanceSalaryTotal> addlistByNew = new ArrayList<>();

		List<TcwFinanceSalaryTotal> salelistByNew = new ArrayList<>();

		//获取销售部数据
		List<TcwFinanceSalaryTotal> addlistBySale = addlist.stream().filter(item->item.getDeptType()==1).collect(Collectors.toList());

		//销售部数据按公司信息分组
		Map<String, List<TcwFinanceSalaryTotal>> saleGroupsByOrgId = addlistBySale.stream().collect(Collectors.groupingBy(e->e.getOrgId()));
		saleGroupsByOrgId.forEach((k, v) -> {
			TcwFinanceSalaryTotal entity = countTotal(v);
			entity.setOrgId(k);//组织机构id、所属公司
			entity.setCountMonth(countMonth);//统计年月
			entity.setDeptName("销售部");
			entity.setCountType(0);
			entity.setDeptType(1);
			entity.setStatus(1);
			salelistByNew.add(entity);
		});

		if(salelistByNew!=null && salelistByNew.size()>0){
			boolean saleIsAdd = false;
			for(TcwFinanceSalaryTotal item : addlist){
				if(item.getDeptType()==0){
					addlistByNew.add(item);
				}else {
					if(!saleIsAdd && salelistByNew.size()>0){
						//添加销售数据
						for(TcwFinanceSalaryTotal itemBySale : salelistByNew){
							addlistByNew.add(itemBySale);
						}
						saleIsAdd = true;
					}
				}
			}
		}

		//先删除
		financeMapper.deleteTcwFinanceSalaryTotalByCountMonth(countMonth);

		//新增
		if(addlistByNew!=null && addlistByNew.size()>0){
			int addCount = 50;
			for(int i=0;i<addlistByNew.size()+addCount;i=i+addCount){
				//批量
				List<TcwFinanceSalaryTotal> newlist = addlistByNew.stream().skip(i).limit(addCount).collect(Collectors.toList());
				financeMapper.insertTcwFinanceSalaryTotalByList(newlist);
			}
		}

		return R.ok();
	}

	public TcwFinanceSalaryTotal countTotal(List<TcwFinanceSalaryTotal> list){
		TcwFinanceSalaryTotal entity = new TcwFinanceSalaryTotal();
		BigDecimal wagesPay = list.stream().map(TcwFinanceSalaryTotal::getWagesPay).reduce(BigDecimal.ZERO,BigDecimal::add);//应发工资
		BigDecimal retirementCompany = list.stream().map(TcwFinanceSalaryTotal::getRetirementCompany).reduce(BigDecimal.ZERO,BigDecimal::add);//养老保险（单位）
		BigDecimal retirementPersonal = list.stream().map(TcwFinanceSalaryTotal::getRetirementPersonal).reduce(BigDecimal.ZERO,BigDecimal::add);//养老保险（个人）
		BigDecimal loseWorkCompany = list.stream().map(TcwFinanceSalaryTotal::getLoseWorkCompany).reduce(BigDecimal.ZERO,BigDecimal::add);//失业保险（单位）
		BigDecimal loseWorkPersonal = list.stream().map(TcwFinanceSalaryTotal::getLoseWorkPersonal).reduce(BigDecimal.ZERO,BigDecimal::add);//失业保险（个人）
		BigDecimal injuryCompany = list.stream().map(TcwFinanceSalaryTotal::getInjuryCompany).reduce(BigDecimal.ZERO,BigDecimal::add);//工伤保险（单位）
		BigDecimal healthCompany = list.stream().map(TcwFinanceSalaryTotal::getHealthCompany).reduce(BigDecimal.ZERO,BigDecimal::add);//医疗保险（单位）
		BigDecimal healthPersonal = list.stream().map(TcwFinanceSalaryTotal::getHealthPersonal).reduce(BigDecimal.ZERO,BigDecimal::add);//医疗保险（个人）
		BigDecimal birthCompany = list.stream().map(TcwFinanceSalaryTotal::getBirthCompany).reduce(BigDecimal.ZERO,BigDecimal::add);//生育保险（单位）
		BigDecimal accumulationFundCompany = list.stream().map(TcwFinanceSalaryTotal::getAccumulationFundCompany).reduce(BigDecimal.ZERO,BigDecimal::add);//公积金（单位）
		BigDecimal accumulationFundPersonal = list.stream().map(TcwFinanceSalaryTotal::getAccumulationFundPersonal).reduce(BigDecimal.ZERO,BigDecimal::add);//公积金（个人）
		BigDecimal personalTax = list.stream().map(TcwFinanceSalaryTotal::getPersonalTax).reduce(BigDecimal.ZERO,BigDecimal::add);//个人所得税
		BigDecimal realityPaySlip = list.stream().map(TcwFinanceSalaryTotal::getRealityPaySlip).reduce(BigDecimal.ZERO,BigDecimal::add);//实发工资
		BigDecimal accumulationFundTotal = list.stream().map(TcwFinanceSalaryTotal::getAccumulationFundTotal).reduce(BigDecimal.ZERO,BigDecimal::add);//公积金合计
		BigDecimal soseBase = list.stream().map(TcwFinanceSalaryTotal::getSoseBase).reduce(BigDecimal.ZERO,BigDecimal::add);//社保基数
		BigDecimal miBase = list.stream().map(TcwFinanceSalaryTotal::getMiBase).reduce(BigDecimal.ZERO,BigDecimal::add);//医保基数
		BigDecimal housingPfBase = list.stream().map(TcwFinanceSalaryTotal::getHousingPfBase).reduce(BigDecimal.ZERO,BigDecimal::add);//公积金基数
		BigDecimal soseTotal = list.stream().map(TcwFinanceSalaryTotal::getSoseTotal).reduce(BigDecimal.ZERO,BigDecimal::add);//社保合计
		BigDecimal miTotal = list.stream().map(TcwFinanceSalaryTotal::getMiTotal).reduce(BigDecimal.ZERO,BigDecimal::add);//医保合计
		BigDecimal otherCost = list.stream().map(TcwFinanceSalaryTotal::getOtherCost).reduce(BigDecimal.ZERO,BigDecimal::add);//其他费用
		BigDecimal wagesAmount = list.stream().map(TcwFinanceSalaryTotal::getWagesAmount).reduce(BigDecimal.ZERO,BigDecimal::add);//工资


		entity.setPersonalTaxAdjust(BigDecimal.ZERO);//个人所得税调整补发
		entity.setWagesPay(wagesPay);//应发工资
		entity.setRetirementCompany(retirementCompany);//养老保险（单位）
		entity.setRetirementPersonal(retirementPersonal);//养老保险（个人）
		entity.setLoseWorkCompany(loseWorkCompany);//失业保险（单位）
		entity.setLoseWorkPersonal(loseWorkPersonal);//失业保险（个人）
		entity.setInjuryCompany(injuryCompany);//工伤保险（单位）
		entity.setHealthCompany(healthCompany);//医疗保险（单位）
		entity.setHealthPersonal(healthPersonal);//医疗保险（个人）
		entity.setBirthCompany(birthCompany);//生育保险（单位）
		entity.setAccumulationFundCompany(accumulationFundCompany);//公积金（单位）
		entity.setAccumulationFundPersonal(accumulationFundPersonal);//公积金（个人）
		entity.setPersonalTax(personalTax);//个人所得税
		entity.setRealityPaySlip(realityPaySlip);//实发工资
		entity.setAccumulationFundTotal(accumulationFundTotal);//公积金合计
		entity.setSoseBase(soseBase);//社保基数
		entity.setMiBase(miBase);//医保基数
		entity.setHousingPfBase(housingPfBase);//公积金基数
		//社保合计
		entity.setSoseTotal(soseTotal);
		//医保合计
		entity.setMiTotal(miTotal);

		entity.setOtherCost(otherCost);//其他费用
		entity.setWagesAmount(wagesAmount);//工资

		return entity;
	}


	public TcwFinanceSalaryTotal addCountDate(Map<String, Object> countItem){
		TcwFinanceSalaryTotal entity = new TcwFinanceSalaryTotal();
		entity.setOrgId(countItem.get("orgId").toString());//组织机构id、所属公司
		entity.setWagesPay(new BigDecimal(countItem.get("wagesPay").toString()));//应发工资
		entity.setRetirementCompany(new BigDecimal(countItem.get("retirementCompany").toString()));//养老保险（单位）
		entity.setRetirementPersonal(new BigDecimal(countItem.get("retirementPersonal").toString()));//养老保险（个人）
		entity.setLoseWorkCompany(new BigDecimal(countItem.get("loseWorkCompany").toString()));//失业保险（单位）
		entity.setLoseWorkPersonal(new BigDecimal(countItem.get("loseWorkPersonal").toString()));//失业保险（个人）
		entity.setInjuryCompany(new BigDecimal(countItem.get("injuryCompany").toString()));//工伤保险（单位）
		entity.setHealthCompany(new BigDecimal(countItem.get("healthCompany").toString()));//医疗保险（单位）
		entity.setHealthPersonal(new BigDecimal(countItem.get("healthPersonal").toString()));//医疗保险（个人）
		entity.setBirthCompany(new BigDecimal(countItem.get("birthCompany").toString()));//生育保险（单位）
		entity.setAccumulationFundCompany(new BigDecimal(countItem.get("accumulationFundCompany").toString()));//公积金（单位）
		entity.setAccumulationFundPersonal(new BigDecimal(countItem.get("accumulationFundPersonal").toString()));//公积金（个人）
		entity.setPersonalTax(new BigDecimal(countItem.get("personalTax").toString()));//个人所得税
		entity.setRealityPaySlip(new BigDecimal(countItem.get("realityPaySlip").toString()));//实发工资
		entity.setPersonalTaxAdjust(BigDecimal.ZERO);//个人所得税调整补发
		entity.setAccumulationFundTotal(new BigDecimal(countItem.get("accumulationFundCompany").toString()).add(new BigDecimal(countItem.get("accumulationFundPersonal").toString())));//公积金合计
		entity.setSoseBase(new BigDecimal(countItem.get("soseBase").toString()));//社保基数
		entity.setMiBase(new BigDecimal(countItem.get("miBase").toString()));//医保基数
		entity.setHousingPfBase(new BigDecimal(countItem.get("housingPfBase").toString()));//公积金基数
		entity.setOtherCost(new BigDecimal(countItem.get("otherCost").toString()));//其他费用
		entity.setWagesAmount(new BigDecimal(countItem.get("wagesAmount").toString()));//工资
		//社保合计
		entity.setSoseTotal(entity.getRetirementCompany()
				.add(entity.getRetirementPersonal())
				.add(entity.getLoseWorkCompany())
				.add(entity.getLoseWorkPersonal())
				.add(entity.getInjuryCompany()));
		//医保合计
		entity.setMiTotal(entity.getHealthCompany()
				.add(entity.getHealthPersonal())
				.add(entity.getBirthCompany()));
		entity.setStatus(1);
		return entity;
	}


	/**
	 * 获取小计表中所有的公司信息
	 */
	@Override
	public List<Map<String, Object>> getOrgNameList(String countMonth) throws Exception{
		return financeMapper.getOrgNameByFinanceSalaryTotal(countMonth);
	}

	/**
	 * 获取小计表中对应公司的统计信息
	 */
	@Override
	public List<Map<String, Object>> countFinanceSalaryTotalByOrgId(String countMonth) throws Exception{
		return financeMapper.countFinanceSalaryTotalByOrgId(countMonth);
	}


	/**
	 * 获取工资表中所有的公司信息
	 */
	@Override
	public List<Map<String, Object>> getOrgNameByUserPaySlip(String countMonth) throws Exception{
		return financeMapper.getOrgNameByUserPaySlip(countMonth);
	}

	/**
	 * 获取工资表中对应公司的统计信息
	 */
	@Override
	public List<Map<String, Object>> countUserPaySlipByOrgId(String countMonth) throws Exception{
		return financeMapper.countUserPaySlipByOrgId(countMonth);
	}
}
